package cn.virens.web.components.open.wxmp.oauth;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;

import cn.hutool.core.util.IdUtil;
import cn.virens.Assert;
import cn.virens.exception.APIException;
import cn.virens.web.components.open.wxmp.WxMpServiceImpl;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;

@Component
public class WxMpOauthSeviceImpl implements WxMpOauthSevice, InitializingBean {
	public static final String DEFAULT_CACHE_NAME = "weixin-mp-oauth";

	private String cacheName = DEFAULT_CACHE_NAME;

	private Cache mChache;

	@Autowired
	private WxMpServiceImpl wxService;

	@Autowired
	@Qualifier("springCacheManager")
	private CacheManager mCacheManager;

	@Override
	public String oauth2BuildAuthURI(String redirectURI, String targetURI) throws Exception {
		String scope = WxConsts.OAuth2Scope.SNSAPI_USERINFO;
		String state = IdUtil.fastSimpleUUID();

		// 生成授权地址
		String result = wxService.oauth2buildAuthorizationUrl(redirectURI, scope, state);
		if (result == null || result.isEmpty()) {
			throw new APIException("ERROR", "生成授权地址失败");
		} else {
			this.mChache.put(state, targetURI);
		}

		return result;
	}

	@Override
	public String oauth2GetTargetURI(String code, String state) throws Exception {
		WxMpOAuth2AccessToken token = wxService.oauth2getAccessToken(code);
		if (token == null) throw new APIException("AUTH_ERR", "授权失败");

		// 获取当前用户的微信信息
		WxMpUser mpUser = wxService.oauth2getUserInfo(token, null);
		if (mpUser == null) throw new APIException("USER_ERR", "获取失败");

		String result = null;

		// 获取缓存中的回调地址
		Object cacheVal = mChache.get(state, Object.class);
		if (cacheVal == null || !(cacheVal instanceof String)) {
			throw new APIException("EMPTY", "回调地址为空");
		} else {
			result = (String) cacheVal;
		}

		// 将state值传递给最终回调地址，方便对应html获取用户信息
		if (StringUtils.endsWithAny(result, "?", "&")) {
			result = result + "_state_=" + state;
		} else if (StringUtils.contains(result, '?')) {
			result = result + "&_state_=" + state;
		} else {
			result = result + "?_state_=" + state;
		}

		// 将用户信息存入缓存
		mChache.put(state, mpUser);

		return result;
	}

	@Override
	public WxMpUser oauth2GetUserinfo(String state) {
		ValueWrapper wrapper = mChache.get(Assert.isEmpty(state, "授权值为空"));
		if (wrapper == null || !(wrapper.get() instanceof WxMpUser)) {
			throw new APIException("EMPTY", "用户信息为空");
		} else {
			return (WxMpUser) wrapper.get();
		}
	}

	@Override
	public void switchoverTo(String appid) {
		this.wxService.switchoverTo(appid);
	}

	@Override
	public WxJsapiSignature signJsapi(String url) throws Exception {
		return wxService.createJsapiSignature(url);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		this.mChache = mCacheManager.getCache(cacheName);
	}

}
